#include "precomp.h"
#include <stdio.h>

#include "game.h"
#include "World.h"
#include "Entity/Entity.h"
#include "Map/Grid.h"

namespace Tmpl {

static Vec2f gOffset = Vec2f(0,0);
static float gZoom = 100.0f;

static Timer gWorldTimer;
static Timer gRenderTimer;
static float gUpdateWorldTimer = 0.0f;
HANDLE gUpdateDone = CreateEvent(NULL, TRUE, TRUE, NULL);

void Game::Init()
{
	Log::OpenConsole();

	// Start Jobmanager
	JobManager::Init( SystemGetCoresCount() );

	// Start LUA
	LuaWrapper::Init();

	//LuaWrapper::RegisterFunction("Average", funcToCalcAverage);
	//LuaWrapper::ExecuteFile("test.lua");
	//LuaWrapper::LoadFile("scripts/test.lua");
	//LuaWrapper::ExecuteLuaFunction("Start");

	// Create the World
	gUpdateWorldTimer = 0.0f;
	gWorldTimer.Start();
	World::Init();
	World::GenerateMap(0, 1);

	ResetEvent(gUpdateDone);
	JobHandle worldUpdate = World::Update(DEPENDENCY_NONE);
	JobHandle jobUpdateDone = JobManager::SetAnEventJob(gUpdateDone);
	JobManager::AddJobDependency(jobUpdateDone, worldUpdate);
	JobManager::AddExecuteJob(jobUpdateDone);
	WaitForSingleObject(gUpdateDone, INFINITE);
	gWorldTimer.Stop();

	Log::Print("Time Expired: %f", gWorldTimer.GetElapsed());
}
void Game::Tick(float dt)
{	
	// Update World
	gUpdateWorldTimer = gUpdateWorldTimer + dt;
	if (gUpdateWorldTimer > WORLD_STEP_TIME)
	{
		gWorldTimer.Start();
		gUpdateWorldTimer -= WORLD_STEP_TIME;

		ResetEvent(gUpdateDone);
		JobHandle worldUpdate = World::Update(DEPENDENCY_NONE);
		JobHandle jobUpdateDone = JobManager::SetAnEventJob(gUpdateDone);
		JobManager::AddJobDependency(jobUpdateDone, worldUpdate);
		JobManager::AddExecuteJob(jobUpdateDone);
		//Log::Print("JobCount: %d", JobManager::GetJobCount());
		WaitForSingleObject(gUpdateDone, INFINITE);
		MessageSystem::HandleAllMessages();
		gWorldTimer.Stop();
	}

	if (key.IsDown(TK_SPACE))
	{
		World::Clear();
	}

	/*
	//if (mouse.IsClicked(0))
	{
		int count = World::GetEntityCount();
		for (int i=0; i<count; ++i)
		{
			MessageSystem::AddMsgDamageDone(MSG_ID_IRRELEVANT, World::GetEntity(i)->GetId(), 1.0f);  
		}
	}
	*/

	/*
	if (mouse.IsClicked(0))
	{
		Ray2f ray = Ray2f(Vec2f(10,10), Vec2f(2500,2500));
		Vec2f outPos;
		Vec2f outNormal;
		int colId = Grid::GetRayIntersectCollisionId(ray, outPos, outNormal);
	}
	*/
	
	gRenderTimer.Start();
	Draw::Clear();

	float speed = 10.0f;
	if (key.IsDown(TK_SHIFT)) speed *= 10.0f;
	if (key.IsDown('A')) gOffset.x -= speed * dt;
	if (key.IsDown('D')) gOffset.x += speed * dt;
	if (key.IsDown('W')) gOffset.y -= speed * dt;
	if (key.IsDown('S')) gOffset.y += speed * dt;
	if (key.IsDown('Q')) gZoom -= speed * dt;
	if (key.IsDown('E')) gZoom += speed * dt;

	glPushMatrix();
	glScalef(gZoom, gZoom, 1.0f);
	glTranslatef(-gOffset.x, -gOffset.y, 0.0f);
	World::Render(dt, gOffset, gZoom);
	glPopMatrix();

	gRenderTimer.Stop();

	char buffer[256];

	TmplFont.Print("World Update: ", 2, 2, 0xFFFFFFFF, Font::LEFT, Font::TOP);
	sprintf_s(buffer, "%2.3f ms", gWorldTimer.GetElapsed() * 1000.0f);
	TmplFont.Print(buffer, 102, 2, 0xFFFFFFFF, Font::LEFT, Font::TOP);

	TmplFont.Print("World Render: ", 2, 12, 0xFFFFFFFF, Font::LEFT, Font::TOP);
	sprintf_s(buffer, "%2.3f ms", gRenderTimer.GetElapsed() * 1000.0f);
	TmplFont.Print(buffer, 102, 12, 0xFFFFFFFF, Font::LEFT, Font::TOP);

	TmplFont.Print("Entities: ", 2, 22, 0xFFFFFFFF, Font::LEFT, Font::TOP);
	sprintf_s(buffer, "%d", World::GetEntityCount());
	TmplFont.Print(buffer, 102, 22, 0xFFFFFFFF, Font::LEFT, Font::TOP);

	TmplFont.Print("CamPos: ", 2, 32, 0xFFFFFFFF, Font::LEFT, Font::TOP);
	sprintf_s(buffer, "%2.2f %2.2f (%2.2f)", gOffset.x, gOffset.y, gZoom);
	TmplFont.Print(buffer, 102, 32, 0xFFFFFFFF, Font::LEFT, Font::TOP);
}

void Game::Shutdown()
{
	LuaWrapper::Exit();
}

}; // namespace Tmpl
